package com.htfyun.ft.fragment.factory;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.ListView;
import android.widget.TextView;

import com.htfyun.ft.BluetoothBondManager.BluetoothBondManager;
import com.htfyun.ft.BluetoothBondManager.OnBluetoothAllListener;
import com.htfyun.ft.R;
import com.htfyun.ft.utils.DebugLog;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;

public class FragmentBluetooth_with_list extends FactoryBaseFragment
        implements View.OnClickListener, OnBluetoothAllListener,
        CompoundButton.OnCheckedChangeListener,
        AdapterView.OnItemClickListener {

    private final Object flagScan = new Object();
    private final Object flagScanning = new Object();
    private Button btnScan;
    private ListView listFond;
    private ListView listBond;

    private TextView txtInfo;

    private SwitchCompat btSwitch;

    private Button btnSelectSystemSetting;

    private BluetoothBondManager bluetoothBondManager;

    private Map<String, BluetoothDevice> fondBTDeviceMap = new HashMap<>();
    private Map<String, BluetoothDevice> bondBTDeviceMap = new HashMap<>();

    private BTDeviceAdapter fondDeviceAdapter;
    private BTDeviceAdapter bondDeviceAdapter;

    private String bondBluetoothAddress = "";

    @Override
    protected int getLayoutRes() {
        return R.layout.fragment_factory_bluetooth_with_list;
    }

    @Override
    protected void onInitView(@Nullable Bundle savedInstanceState) {
        super.onInitView(savedInstanceState);

        txtInfo = findViewById(R.id.txtInfo);

        btnScan = findViewById(R.id.btnScan);
        btnSelectSystemSetting = findViewById(R.id.btnSelectSystemSetting);
        btnScan.setOnClickListener(this);
        btnSelectSystemSetting.setOnClickListener(this);

        listFond = (ListView) findViewById(R.id.listFond);
        listBond = (ListView) findViewById(R.id.listBond);

        btSwitch = (SwitchCompat) findViewById(R.id.btSwitch);
        btSwitch.setOnCheckedChangeListener(this);


        listFond.setAdapter(fondDeviceAdapter);
        listBond.setAdapter(bondDeviceAdapter);

        fondDeviceAdapter = new BTDeviceAdapter(mContext, -1);
        bondDeviceAdapter = new BTDeviceAdapter(mContext, -1);

        listFond.setAdapter(fondDeviceAdapter);
        listBond.setAdapter(bondDeviceAdapter);

        listFond.setOnItemClickListener(this);
        listBond.setOnItemClickListener(this);

        setBtnPassVisibility(View.INVISIBLE);
    }

    @Override
    protected void onVisible() {
        super.onVisible();

        initBT();
    }

    @Override
    protected void onInvisible() {
        super.onInvisible();

        deInitBT();
    }

    private void updateScanBtn() {
        getHandler().post(new Runnable() {
            @Override
            public void run() {

                if (bluetoothBondManager.isDiscovering()) {
                    btnScan.setText(R.string.ft_bt_scanning);
                    btnScan.setTag(flagScanning);
                } else {
                    btnScan.setText(R.string.ft_bt_scan);
                    btnScan.setTag(flagScan);
                }

            }
        });

    }

    private synchronized void updateFondDeviceList() {
        fondDeviceAdapter.setNotifyOnChange(false);
        fondDeviceAdapter.clear();

        fondDeviceAdapter.setNotifyOnChange(true);
        fondDeviceAdapter.addAll(fondBTDeviceMap.values());
    }

    private synchronized void updateBondDeviceList() {
        bondDeviceAdapter.setNotifyOnChange(false);
        bondDeviceAdapter.clear();

        bondDeviceAdapter.setNotifyOnChange(true);
        bondDeviceAdapter.addAll(bondBTDeviceMap.values());
    }

    private void setSwitchStatus(boolean on) {
        btSwitch.setOnCheckedChangeListener(null);
        btSwitch.setChecked(on);
        btSwitch.setOnCheckedChangeListener(this);
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        setBluetoothEnabled(isChecked);
    }

    @Override
    public void onClick(View v) {
        if (v == btnScan) {

            if (btnScan.getTag() == flagScanning) {

                bluetoothBondManager.cancelDiscovery();

            } else {

                startDiscovery();
            }

        } else if (v == btnSelectSystemSetting) {

            startBTSettings();

        }
    }

    @Override
    public void onBluetoothACLConnected(BluetoothDevice device, boolean connected) {
        if (!device.getAddress().equals(bondBluetoothAddress)) {
            return;
        }

        if (!connected) {

            onBluetoothDisconnected(device);

        }
    }

    @Override
    public void onBluetoothBonding(BluetoothDevice device) {
        if (!device.getAddress().equals(bondBluetoothAddress)) {
            return;
        }

        String name = device.getName();
        if (TextUtils.isEmpty(name)) {
            name = device.getAddress();
        }
        String status = getString(R.string.bt_bonding_status, name);
        updateTxtInfo(status);

        bondBTDeviceMap.put(device.getAddress(), device);
        fondBTDeviceMap.remove(device.getAddress());
        updateBondDeviceList();
        updateFondDeviceList();
    }

    @Override
    public void onBluetoothBonded(BluetoothDevice device) {
        if (!device.getAddress().equals(bondBluetoothAddress)) {
            return;
        }

        String name = device.getName();
        if (TextUtils.isEmpty(name)) {
            name = device.getAddress();
        }

        String status = getString(R.string.bt_bonded_status, name);
        updateTxtInfo(status);

        getHandler().sendEmptyMessageDelayed(MSG_SET_BTNPASS_VISIBLE, DELAY_SET_BTNPASS_VISIBLE);

    }

    @Override
    public void onBluetoothConnected(BluetoothDevice device, int profile) {

    }

    @Override
    public void onBluetoothDisconnected(BluetoothDevice device, int profile) {

    }

    @Override
    public void onDiscoveryStarted() {
        updateScanBtn();
    }

    @Override
    public void onDiscoveryFinished() {
        updateScanBtn();
    }

    @Override
    public void onBluetoothEnabled(boolean enabled) {
        setSwitchStatus(enabled);

        if (enabled) {
            startDiscovery();
        }
    }

    @Override
    public void onBluetoothFound(BluetoothDevice device) {
        if (bondBTDeviceMap.get(device.getAddress()) == null) {

            fondBTDeviceMap.put(device.getAddress(), device);

            updateFondDeviceList();
        }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        BluetoothDevice device = null;
        if (parent == listFond) {
            device = fondDeviceAdapter.getItem(position);
        } else if (parent == listBond) {
            device = bondDeviceAdapter.getItem(position);
        }

        if (device == null) {
            return;
        }
        DebugLog.e("device addr = " + device.getAddress() + ", name = " + device.getName());

        bondBluetoothAddress = device.getAddress();
        bluetoothBondManager.bondDevice(device);
    }


    private class BTDeviceAdapter extends ArrayAdapter<BluetoothDevice> {

        public BTDeviceAdapter(@NonNull Context context, int resource) {
            super(context, resource);
        }

        @NonNull
        @Override
        public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView != null) {
                holder = (ViewHolder) convertView.getTag();
            }
            if (holder == null) {
                holder = new ViewHolder();
                convertView = getLayoutInflater().inflate(R.layout.item_bt_devices, null);
                holder.txtName = (TextView) convertView.findViewById(R.id.txtName);

                convertView.setTag(holder);
            }

            BluetoothDevice device = getItem(position);

            if (device != null) {

                String name = device.getName();
                if (TextUtils.isEmpty(name)) {
                    name = device.getAddress();
                }
                holder.txtName.setText(name);

            }

            return convertView;
        }
    }

    private final class ViewHolder {
        private TextView txtName;
    }

    private void initBT() {

        if (bluetoothBondManager == null) {
            bluetoothBondManager = new BluetoothBondManager(mContext);

            bluetoothBondManager.setEnabledListener(this);
            bluetoothBondManager.setBondListener(this);
            bluetoothBondManager.setDiscoveryListener(this);
            bluetoothBondManager.setFoundListener(this);
            bluetoothBondManager.setAclConnectedListener(this);

            bluetoothBondManager.registerBTReceiver();
            startDiscovery();

        }

    }

    private void deInitBT() {
        DebugLog.e("btOnDestroy");

        if (bluetoothBondManager != null) {

            bluetoothBondManager.unregisterBTReceiver();

            bluetoothBondManager.setEnabledListener(null);
            bluetoothBondManager.setBondListener(null);
            bluetoothBondManager.setDiscoveryListener(null);
            bluetoothBondManager.setFoundListener(null);
            bluetoothBondManager.setAclConnectedListener(null);

            bluetoothBondManager.cancelDiscovery();
            bluetoothBondManager.disconnectAllProfile();

            Set<BluetoothDevice> deviceList = bluetoothBondManager.getBluetoothAdapter().getBondedDevices();

            if (deviceList != null && !deviceList.isEmpty()) {
                for (BluetoothDevice device : deviceList) {
                    bluetoothBondManager.removeBond(device);
                }
            }

            bluetoothBondManager.closeBluetooth();
            bluetoothBondManager = null;
        }
    }


    private void startDiscovery() {

        if (bluetoothBondManager.isBluetoothEnabled()) {

            fondBTDeviceMap.clear();
            updateFondDeviceList();

            Set<BluetoothDevice> deviceList = bluetoothBondManager.getBluetoothAdapter().getBondedDevices();

            bondBTDeviceMap.clear();

            if (deviceList != null && !deviceList.isEmpty()) {
                for (BluetoothDevice device : deviceList) {
                    bondBTDeviceMap.put(device.getAddress(), device);
                }
            }
            updateBondDeviceList();

            bluetoothBondManager.startDiscovery();

            return;
        }

        setBluetoothEnabled(true);

    }

    private void setBluetoothEnabled(boolean enabled) {

        if (enabled) {
            bluetoothBondManager.openBluetooth();

        } else {
            bluetoothBondManager.cancelDiscovery();
            bluetoothBondManager.closeBluetooth();
        }

        bondBTDeviceMap.clear();
        fondBTDeviceMap.clear();
        updateBondDeviceList();
        updateFondDeviceList();

    }

    private void startBTSettings() {

        startAndroidBluetoothSettings();
    }

    private boolean startAndroidBluetoothSettings() {

        try {

            Intent intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
            startActivity(intent);

        } catch (Exception e) {

            return false;
        }

        return true;
    }

    private void onBluetoothDisconnected(BluetoothDevice device) {

        setBtnPassVisibility(View.INVISIBLE);
        bluetoothBondManager.removeBond(device);

        String name = device.getName();
        if (TextUtils.isEmpty(name)) {
            name = device.getAddress();
        }
        String status = getString(R.string.bt_disconnected_status, name);
        updateTxtInfo(status);

        startDiscovery();
    }


    private void updateTxtInfo(String txt) {
        getHandler().obtainMessage(MSG_UPDATE_TXT_INFO, txt).sendToTarget();

    }

    ////////////////////////////////////////////////
    ////////////////////////////////////////////////

    private final static int MSG_UPDATE_TXT_INFO = 2000;

    private final static int MSG_SET_BTNPASS_VISIBLE = 2001;
    private final static int DELAY_SET_BTNPASS_VISIBLE = 5000;//5s


    @Override
    protected void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_UPDATE_TXT_INFO:
                if (msg.obj instanceof String) {
                    txtInfo.setText((String) msg.obj);
                }
                break;
            case MSG_SET_BTNPASS_VISIBLE:
                setBtnPassVisibility(View.VISIBLE);
                break;

        }
    }



}
